using UnityEngine;
using System.Collections;

public class CameraOmniVision : MonoBehaviour {
    static private CameraOmniVision instance;
    static public CameraOmniVision GetInstance()
    {
        return instance;
    }
	private Vector3 SCREEN_UP;
	private int screenWidth;
	private int screenHeight;
	//El (0,0) es abajo-izquierda.
	private int innerWidthThreshold;
	private int outerWidthThreshold;
	private int innerHeightThreshold;
	private int outerHeightThreshold;
	
	private Vector3 moveDirection;
	
	public float slowSpeed;
	public float highSpeed;
	
	public int innerThreshold;
	public int outerThreshold;
	public float zoomFactor;
	
	public Transform targetToFollow;
	private bool zooming;
	private Vector3 zoomingTarget;
	
	private bool translating;
	private Vector3 translatingTarget;
	
	private bool isUpdating;
	// Use this for initialization
	void Start () {
        instance = this;
		isUpdating = false;
		SCREEN_UP = Vector3.forward;
		moveDirection = Vector3.zero;
/*		slowSpeed = 1;
		highSpeed = 3;
*/		
		screenWidth = (int)this.camera.GetScreenWidth();
		screenHeight = (int)this.camera.GetScreenHeight();
		
		outerWidthThreshold = screenWidth*outerThreshold/100;
		outerHeightThreshold = screenHeight*outerThreshold/100;
		innerWidthThreshold = (screenWidth*innerThreshold/100) + outerWidthThreshold;
		innerHeightThreshold = (screenHeight*innerThreshold/100) + outerHeightThreshold;
		
		Debug.Log("H:" + screenHeight);
		Debug.Log("W:" + screenWidth);
	}
	
	// Update is called once per frame
	void Update () {
//		Debug.Log(isUpdating);
		CheckBounds();
		MoveCamera();
		if (zooming)
			KeepZooming();
		
		if (Input.GetKeyDown(KeyCode.LeftArrow) )
			RotateLeft();
		if (Input.GetKeyDown(KeyCode.RightArrow) )
			RotateRight();
		if (Input.GetKeyDown(KeyCode.UpArrow) )
			ZoomIn();
		if (Input.GetKeyDown(KeyCode.DownArrow) )
			ZoomOut();
        if (m_IsShaderActive)
        {
            UpdateShaders();
        }

	}
	private void CheckBounds(){
		moveDirection = Vector3.zero;
		//Verifico posición Horizontal.
		if (Input.mousePosition.x <= outerWidthThreshold){
			moveDirection += -this.transform.right*highSpeed;
		}
		else if (Input.mousePosition.x > outerWidthThreshold &&
		Input.mousePosition.x <= innerWidthThreshold){
			moveDirection += -this.transform.right*slowSpeed;
		}
		else if (Input.mousePosition.x >= screenWidth-outerWidthThreshold){
			moveDirection += this.transform.right*highSpeed;	
		}
		else if (Input.mousePosition.x >= screenWidth-innerWidthThreshold &&
		Input.mousePosition.x < screenWidth-outerWidthThreshold){
			moveDirection += this.transform.right*slowSpeed;
		}
		//Verifico posición Vertical.
		if (Input.mousePosition.y <= outerHeightThreshold){
			moveDirection += -SCREEN_UP*highSpeed;
		}
		else if (Input.mousePosition.y > outerHeightThreshold &&
		Input.mousePosition.y <= innerHeightThreshold){
			moveDirection += -SCREEN_UP*slowSpeed;	
		}
		else if (Input.mousePosition.y >= screenHeight-outerHeightThreshold){
			moveDirection += SCREEN_UP*highSpeed;
		}
		else if (Input.mousePosition.y >= screenHeight-innerHeightThreshold &&
		Input.mousePosition.y < screenWidth-outerHeightThreshold){
			moveDirection += SCREEN_UP*slowSpeed;	
		}
	}
	private void MoveCamera(){
		this.transform.position += moveDirection*Time.deltaTime;
	}
	private void RotateLeft(){
		if (isUpdating)
			return;
		this.transform.RotateAround(GetCameraCenter(), Vector3.up, 90);
		UpdateScreenUp(-90);
		isUpdating = false;
	}
	private void RotateRight(){
		if (isUpdating)
			return;
		this.transform.RotateAround(GetCameraCenter(), Vector3.up, -90);
		UpdateScreenUp(90);
		isUpdating = false;
	}
	private void ZoomIn(){
		if (isUpdating)
			return;
		zoomingTarget =
			this.transform.position + this.transform.forward*zoomFactor;
		zooming = true;
		isUpdating = true;
	}	
	private void ZoomOut(){
		if (isUpdating)
			return;
		zoomingTarget =
			this.transform.position - this.transform.forward*zoomFactor;
		zooming = true;
		isUpdating = true;
	}
	private void KeepZooming(){
		if (Vector3.Distance(this.transform.position,zoomingTarget) < 1){
			this.transform.position = zoomingTarget;
			zooming = false;
			isUpdating = false;
		} else{
			Vector3 movement =
				Vector3.Lerp(this.transform.position, zoomingTarget, 0.1f);
			this.transform.position = movement;
		}
	}
	public void TranslateToPosition(Vector3 position){
	
		Vector3 center = GetCameraCenter();
		Vector3 difference = position - center;
		difference.y = 0;
		this.transform.position += difference;
	}
	private void UpdateScreenUp(float angle){
		Vector3 result;
		result.x = (SCREEN_UP.x * Mathf.Cos(Mathf.Deg2Rad*angle) )
				 - (SCREEN_UP.z * Mathf.Sin(Mathf.Deg2Rad*angle) );
		result.y = 0;
		result.z = (SCREEN_UP.x * Mathf.Sin(Mathf.Deg2Rad*angle) ) 
				 + (SCREEN_UP.z * Mathf.Cos(Mathf.Deg2Rad*angle) );
		SCREEN_UP = result;
	}
	private Vector3 GetCameraCenter(){
		//Coseno (ang) = camara.altura / camara.forward.	
		float cameraAngle = Vector3.Angle(transform.forward, Vector3.down);
		float distance = this.transform.position.y / Mathf.Cos(cameraAngle);
		Vector3 center = transform.position + transform.forward*distance;
		Debug.Log(center);
		return center;
    }
#region Shaders

    float m_GreyDuration = 2.0f;
    float m_RedDuration = 4.0f;
    float m_CurrentStrenght = 0;
    bool m_IsShaderActive = false;

    public ColorScaleEffect m_RedEffect;
    public ColorScaleEffect m_GreyEffect;
    /// <summary>
    /// Updatea el tiempo de los shaders para que vallan transitando hacia cierto color.
    /// </summary>
    void UpdateShaders()
    {
        if (m_GreyEffect.enabled)
        {
            if (m_GreyEffect.m_Strength < 1.0f)
            {
                m_GreyEffect.m_Strength += 0.05f / m_GreyDuration;
            }
            else
            {
                m_GreyEffect.m_Strength = 1;
            }
        }
        else if (m_RedEffect.enabled)
        {
            if (m_RedEffect.m_Strength < 1)
            {
                m_RedEffect.m_Strength += 0.05f / m_RedDuration;
            }
            else
            {
                m_RedEffect.m_Strength = 1;
            }
        }
    }
    public void ActivateRedShader()
    {
        m_RedEffect.enabled = true;
        m_IsShaderActive = true;
    }
    public void ActivateGreyShader()
    {
        m_GreyEffect.enabled = true;
        m_IsShaderActive = true;
    }
    public void DeactiveShaders()
    {
        m_RedEffect.enabled = false;
        m_RedEffect.m_Strength = 0;
        m_GreyEffect.enabled = false;
        m_GreyEffect.m_Strength = 0;

        m_IsShaderActive = false;
    }

#endregion

}
